/**
 * 具有progress信息的Promise
 */
export class PromiseProgress<T> extends Promise<T> {
  private _listeners: ((percent: number) => void)[];
  constructor(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void, progress: (percent: number) => void) => void) {
    super((resolve, reject) => executor(resolve, reject,
      (percent: number) => {
        try {
          return this._listeners.forEach((listener: (percent: number) => void) => listener(percent));
        } catch (error) {
          reject(error);
        }
      }));
    this._listeners = [];
  }

  progress(handler: (percent: number) => void) {
    this._listeners.push(handler);
    return this;
  }

  /**
   * 并发多个Promise，和Promise.all相同,只是实现了其中progress。完成后返回结果列表。
   * @param promises 
   * @returns 
   */
  static each(promises: PromiseProgress<any>[] | Promise<any>[]): PromiseProgress<any[]> {
    const results = new Array(promises.length);
    const length = promises.length;
    let resolveCount = 0;
    return new PromiseProgress<any[]>((resolve, reject, progress) => {
      promises.forEach((promise, index) => {
        promise.then(result => {
          results[index] = result;
          progress(++resolveCount / length);
          if (resolveCount === length) resolve(results);
        }).catch(reject);
      });
    });
  }

  /**
   * 队列逐个执行多个Promise。完成后返回结果列表。
   * @param promises 
   * @returns 
   */
  static sequence(promises: PromiseProgress<any>[] | Promise<any>[]): PromiseProgress<any[]> {
    const results: any[] = [];
    const length = promises.length;
    let resolveCount = 0;
    return new PromiseProgress<any[]>((resolve, reject, progress) => {
      function invokeNext() {
        promises[results.length].then(result => {
          results.push(result);
          progress(++resolveCount / length);
          if (results.length === length) resolve(results);
          else invokeNext();
        }).catch(reject);
      }
      invokeNext();
    });
  }
}


